package com.example.testplatform.controller;

import com.example.testplatform.common.LogUtils;
import org.slf4j.Logger;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 前端日志收集控制器
 * 负责接收和处理前端上传的日志信息
 */
@RestController
@RequestMapping("/api/logs")
public class FrontendLogController {

    private static final Logger logger = LogUtils.getLogger(FrontendLogController.class);

    /**
     * 安全类型转换工具方法
     * @param obj 要转换的对象
     * @param targetClass 目标类型
     * @param defaultValue 默认值
     * @param <T> 泛型类型
     * @return 转换后的对象或默认值
     */
    @SuppressWarnings("unchecked")
    private <T> T safeCast(Object obj, Class<?> targetClass, T defaultValue) {
        if (obj == null) {
            return defaultValue;
        }
        try {
            if (targetClass.isInstance(obj)) {
                return (T) targetClass.cast(obj);
            } else if (obj instanceof String && Map.class.isAssignableFrom(targetClass)) {
                // 处理可能的JSON字符串
                return defaultValue;
            }
            return defaultValue;
        } catch (Exception e) {
            LogUtils.debug(logger, () -> "安全转换失败: " + e.getMessage());
            return defaultValue;
        }
    }

    /**
     * 收集前端日志
     * @param logData 前端上传的日志数据
     */
    @PostMapping("/collect")
    public void collectFrontendLogs(@RequestBody Map<String, Object> logData) {
        long startTime = System.currentTimeMillis();
        LogUtils.logSystemEvent(logger, "FRONTEND_LOG_COLLECT_ATTEMPT", "前端日志收集请求开始处理");
        LogUtils.logApiRequest(logger, "POST", "/api/logs/collect", "日志数据接收请求");
        LogUtils.debug(logger, () -> "开始处理前端日志收集请求，请求数据大小=" + (logData != null ? logData.size() : 0));
        
        try {
            // 验证参数
            if (logData == null || logData.isEmpty()) {
                LogUtils.warn(logger, "前端日志收集请求参数为空，忽略处理");
                LogUtils.logSystemEvent(logger, "FRONTEND_LOG_COLLECT_FAILED", "前端日志收集请求参数为空");
                LogUtils.logPerformance(logger, "collectFrontendLogs", startTime, System.currentTimeMillis());
                return;
            }
            
            // 获取日志信息
            LogUtils.debug(logger, () -> "提取前端日志请求中的各项信息");
            @SuppressWarnings("unchecked")
            List<Map<String, Object>> logs = (List<Map<String, Object>>) logData.get("logs");
            Long timestamp = (Long) logData.get("timestamp");
            String environment = (String) logData.get("environment");
            String clientIp = (String) logData.get("clientIp");
            String appVersion = (String) logData.get("appVersion");
            
            // 记录日志收集信息
            LogUtils.logSystemEvent(logger, "FRONTEND_LOG_COLLECT_RECEIVED", 
                "环境: " + environment + ", 日志数量: " + (logs != null ? logs.size() : 0) + ", 客户端IP: " + clientIp + ", 应用版本: " + appVersion + ", 时间戳: " + timestamp);
            
            LogUtils.info(logger, () -> "接收到前端日志收集请求，环境=" + environment + ", 日志数量=" + (logs != null ? logs.size() : 0) + ", 应用版本=" + appVersion);
            
            // 如果有日志数据，处理每条日志
            if (logs != null && !logs.isEmpty()) {
                LogUtils.debug(logger, () -> "准备处理前端日志数据，日志总数=" + logs.size());
                processLogs(logs, environment, clientIp, appVersion);
                LogUtils.logSystemEvent(logger, "FRONTEND_LOG_COLLECT_PROCESSED", "前端日志处理完成，处理日志数量=" + logs.size());
            } else {
                LogUtils.debug(logger, () -> "前端日志收集请求中未包含有效日志数据，跳过处理");
                LogUtils.info(logger, () -> "前端日志收集请求中未包含有效日志数据");
            }
            
            LogUtils.logPerformance(logger, "collectFrontendLogs", startTime, System.currentTimeMillis());
            LogUtils.info(logger, () -> "前端日志收集请求处理完成，耗时=" + (System.currentTimeMillis() - startTime) + "ms");
            
        } catch (Exception e) {
            // 记录处理日志过程中的异常
            LogUtils.logApiError(logger, "POST", "/api/logs/collect", e);
            LogUtils.error(logger, "处理前端日志异常: " + LogUtils.formatException(e));
            LogUtils.logSystemEvent(logger, "FRONTEND_LOG_COLLECT_ERROR", "处理前端日志异常: " + e.getMessage());
            LogUtils.logPerformance(logger, "collectFrontendLogs", startTime, System.currentTimeMillis());
        }
    }

    /**
     * 处理每条日志
     * @param logs 日志列表
     * @param environment 环境信息
     * @param clientIp 客户端IP
     * @param appVersion 应用版本
     */
    private void processLogs(List<Map<String, Object>> logs, final String environment, final String clientIp, final String appVersion) {
        long startTime = System.currentTimeMillis();
        LogUtils.debug(logger, () -> "进入日志处理方法，日志总数=" + logs.size() + ", 环境=" + environment);
        
        int successCount = 0;
        int errorCount = 0;
        
        for (int i = 0; i < logs.size(); i++) {
            final int logIndex = i; // 创建final版本的索引
            final int logNumber = i + 1; // 创建final版本的日志序号
            Map<String, Object> log = logs.get(i);
            LogUtils.debug(logger, () -> "开始处理第" + logNumber + "条日志，日志索引=" + logIndex);
            
            try {
                // 提取日志信息
            String level = safeCast(log.get("level"), String.class, "UNKNOWN");
            String message = safeCast(log.get("message"), String.class, "");
            String module = safeCast(log.get("module"), String.class, "unknown");
            
            // 安全地处理timestamp，防止类型转换异常
            String timestamp;
            Object timestampObj = log.get("timestamp");
            if (timestampObj == null) {
                timestamp = String.valueOf(System.currentTimeMillis());
            } else if (timestampObj instanceof Long) {
                timestamp = String.valueOf(timestampObj);
            } else if (timestampObj instanceof String) {
                timestamp = (String) timestampObj;
            } else {
                timestamp = String.valueOf(timestampObj);
            }
            
            // 安全地转换其他可能引起类型转换异常的字段
            @SuppressWarnings("unchecked")
            Map<String, Object> data = safeCast(log.get("data"), Map.class, new HashMap<>());
            String userId = safeCast(log.get("userId"), String.class, "unknown");
            String url = safeCast(log.get("url"), String.class, "unknown");
            String userAgent = safeCast(log.get("userAgent"), String.class, "unknown");
            String sessionId = safeCast(log.get("sessionId"), String.class, "unknown");

                // 验证必要字段
                if (level == null || message == null) {
                    LogUtils.warn(logger, "跳过处理无效日志: 缺少必要字段(level/message)，日志索引=" + logIndex);
                    errorCount++;
                    continue;
                }
                
                // 根据日志级别记录日志
                String logMessage = String.format("[前端][%s][%s][%s][环境:%s][会话:%s][IP:%s] %s", 
                    timestamp, module, userId, environment, sessionId, clientIp, message);
                
                final String finalLevel = level;
                final String finalModule = module;
                final String finalUserId = userId;
                LogUtils.debug(logger, () -> "处理日志信息 - 级别: " + finalLevel + ", 模块: " + finalModule + ", 用户: " + finalUserId);
                
                switch (level != null ? level.toUpperCase() : "") {
                    case "DEBUG":
                        if (logger.isDebugEnabled()) {
                            logger.debug(logMessage + (data != null ? ", 数据: " + data : ""));
                        }
                        break;
                    case "INFO":
                        LogUtils.info(logger, () -> logMessage + (data != null ? ", 数据: " + data : ""));
                        break;
                    case "WARN":
                        LogUtils.warn(logger, logMessage + (data != null ? ", 数据: " + data : ""));
                        break;
                    case "ERROR":
                    case "FATAL":
                        // 对于错误日志，记录更多上下文信息
                        LogUtils.error(logger, logMessage + ", URL: " + url + ", UserAgent: " + userAgent + ", 应用版本: " + appVersion +
                            (data != null ? ", 数据: " + data : ""));
                        break;
                    default:
                        // 其他级别日志
                        LogUtils.info(logger, () -> logMessage + (data != null ? ", 数据: " + data : ""));
                        break;
                }
                
                successCount++;
                final int currentSuccessCount = successCount;
                LogUtils.debug(logger, () -> "成功处理第" + logNumber + "条日志，日志级别=" + finalLevel + ", 当前成功计数=" + currentSuccessCount);
                
            } catch (Exception e) {
                // 单条日志处理失败不影响其他日志处理
                LogUtils.error(logger, "处理第" + logNumber + "条前端日志异常: " + LogUtils.formatException(e));
                errorCount++;
                final int currentErrorCount = errorCount;
                LogUtils.debug(logger, () -> "处理第" + logNumber + "条日志失败，当前失败计数=" + currentErrorCount);
            }
        }
        
        final int totalLogs = logs.size();
        final int finalSuccessCount = successCount;
        final int finalErrorCount = errorCount;
        LogUtils.logPerformance(logger, "processLogs", startTime, System.currentTimeMillis());
        LogUtils.logSystemEvent(logger, "FRONTEND_LOG_BATCH_PROCESSED", "批量处理前端日志完成，总数=" + totalLogs + ", 成功=" + finalSuccessCount + ", 失败=" + finalErrorCount);
        LogUtils.info(logger, () -> "批量处理前端日志完成，总数=" + totalLogs + ", 成功=" + finalSuccessCount + ", 失败=" + finalErrorCount + ", 耗时=" + (System.currentTimeMillis() - startTime) + "ms");
    }
}